package metaObject;

import java.lang.reflect.Method;

import javassist.tools.reflect.Metaobject;
import stores.StoreEnvirThread;
import fr.upmc.aladyn.transactionables.annotation.Transactionnable;

/**
 * My Meta Object => Make Reflective all Class and Transactionnable method
 * @author 3003064_3153319
 */
public class MyMetaObject extends Metaobject{

	private static final long serialVersionUID = -4523162520719724324L;

	public MyMetaObject(Object self, Object[] args){
		super(self, args);
	}


	/* redefinition de la methode trapMethodCall
	 * elle store tout les objets avant modification
	 * elle restaure la valeur des objects Transactionnable si elle trap une exception
	 * @see javassist.tools.reflect.Metaobject#trapMethodcall(int, java.lang.Object[])
	 */
	public Object trapMethodcall(int identifier, Object[] args) throws Throwable{
		
		Method myMethod = getClassMetaobject().getMethod(identifier);

		Object b = null;

		if(getMethodName(identifier).startsWith("set")){
			StoreEnvirThread.AddObjectInTheLastEnv(getObject());
		}
		
		if(myMethod.isAnnotationPresent(Transactionnable.class)){
			StoreEnvirThread.newEnv();
			StoreEnvirThread.AddObjectInTheLastEnv(getObject());
			try {
				b = super.trapMethodcall(identifier, args);
			} catch(Throwable e ){
				StoreEnvirThread.RestaureAndRemoveLastEnv();
			}
			StoreEnvirThread.DeleteLastEnv();
			return b;
		} 
		
		return super.trapMethodcall(identifier, args);
	}

}
